﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace ExpressionEngine
{
    /// <summary>
    /// 表格管理器，用于管理所有表达式涉及到的语言环境因素
    /// 20151225
    /// </summary>
    public class TableManager
    {
        /// <summary>
        /// 存储表达式语言环境涉及的操作符，包括解析引擎保留操作符以及用户注册的自定义操作符
        /// </summary>
        private static Dictionary<string, Operator> _tblOperator = new Dictionary<string,Operator>();
 
        /// <summary>
        /// 存储表达式语言环境涉及的语法关键字
        /// </summary>
        private static Dictionary<string, Symbol> _tblSyntaxKey = new Dictionary<string,Symbol>();

        /// <summary>
        /// 存储表达式语言环境定义的函数，包括解析引擎内部函数以及用户注册的自定义函数
        /// </summary>
        private static Dictionary<string, Function> _tblFunction = new Dictionary<string, Function>(); 

        /// <summary>
        /// 存储表达式语言环境定义的内置变量
        /// </summary>
        private static Dictionary<string, Variable> _tblGlobalVar = new Dictionary<string, Variable>();

        /// <summary>
        /// 存储表达式语言环境定义的非内置变量
        /// </summary>
        private static Dictionary<string, Variable> _tbUnBuiltInVar = new Dictionary<string, Variable>();
 
        /// <summary>
        /// 标示符最大长度，方便表达式解析过程中的回朔处理
        /// </summary>
        private static int MAX_IDENTIFIER_LEN 	 = 1; 

        /// <summary>
        /// 操作符是否可被重写处理器
        /// </summary>
        private static bool bOverridable = false; 

        /// <summary>
        /// 根据标示符号字符串取得操作符
        /// </summary>
        /// <param name="identifier"></param>
        /// <returns></returns>
        public static Operator GetOperator(string identifier) 
        {
            if (!_tblOperator.ContainsKey(identifier))
                throw new Exception("找不到指定操作符");
          
            return _tblOperator[identifier];
        } 

        /// <summary>
        /// 根据标示符号字符串取得函数
        /// </summary>
        /// <param name="identifier"></param>
        /// <returns></returns>
        public static Function GetFunction(string identifier) 
        {
            if (!_tblFunction.ContainsKey(identifier))
                throw new Exception("找不到指定函数");

            return _tblFunction[identifier];
        } 

        /// <summary>
        /// 根据标示符号字符串取得标示符
        /// </summary>
        /// <param name="escapeStr"></param>
        /// <param name="dimension"></param>
        /// <returns></returns>
        public static List<string> GetIdentifier(string escapeStr)
        {
            List<string> identifyStr = new List<string>();
            foreach (var item in _tblSyntaxKey)
            {
                if (item.Value.Escape == escapeStr)
                    identifyStr.Add(item.Value.Identifier);   
            }

            return identifyStr;
        }

        /// <summary>
        /// 根据变量名取得已注册的变量
        /// </summary>
        /// <param name="varName"></param>
        /// <returns></returns>
        public static Variable GetVariable(string varName)
        {
            if (_tblGlobalVar.ContainsKey(varName))
                return _tblGlobalVar[varName];

            if (_tbUnBuiltInVar.ContainsKey(varName))
                return _tbUnBuiltInVar[varName];

            throw new Exception("找不到指定变量");
        } 

        /// <summary>
        /// 注册操作符
        /// </summary>
        /// <param name="oper"></param>
        /// <returns></returns>
        public static bool RegistOperator(Operator oper)
        {
            if (_tblOperator.ContainsKey(oper.Identifier))
                return false;

            _tblOperator.Add(oper.Identifier, oper);
            RegistSyntaxKeys(oper);
            return true;
        }

        /// <summary>
        /// 注册语法关键字
        /// </summary>
        /// <param name="identifier"></param>
        /// <returns></returns>
        public static bool RegistSyntaxKeys(Symbol symbol) 
        {
            if (_tblSyntaxKey.ContainsKey(symbol.Identifier))
                return false;

            _tblSyntaxKey.Add(symbol.Identifier, symbol);
            return true;
        } 

        /// <summary>
        /// 注册函数
        /// </summary>
        /// <param name="func"></param>
        /// <returns></returns>
        public static bool RegistFunction(Function func) 
        {
            if (_tblFunction.ContainsKey(func.Identifier))
                return false;

            _tblFunction.Add(func.Identifier, func);
            RegistSyntaxKeys(func);
            return true;
        }

        /// <summary>
        /// 注册变量
        /// </summary>
        /// <param name="var"></param>
        /// <returns></returns>
        public static bool RegistVariable(Variable var)
        {
            if (var.BBuiltIn)
            {
                if (_tblGlobalVar.ContainsKey(var.Name))
                    return false;

                _tblGlobalVar.Add(var.Name, var);
            }
            else
            {
                if (_tbUnBuiltInVar.ContainsKey(var.Name))
                    return false;

                _tbUnBuiltInVar.Add(var.Name, var);
            }
            
            return true;
        }

        /// <summary>
        /// 判断是否为取值操作符
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public static bool bValueOperator(string token)
        {
            if (ValueOperator.Instance.Identifier != token)
                return false;

            return true;
        } 

        /// <summary>
        /// 判断是否存在某标示符(转义字符)
        /// </summary>
        /// <param name="identifier"></param>
        /// <returns></returns>
        public static bool ExistIdentifier(string identifier) 
        {
            if (_tblSyntaxKey.ContainsKey(identifier))
                return true;

            return false;
        }

        /// <summary>
        /// 判断是否存在某转义字符（用户输入字符）
        /// </summary>
        /// <param name="escape"></param>
        /// <returns></returns>
        public static bool ExistEscape(string escape)
        {
            foreach (var item in _tblSyntaxKey)
            {
                if (item.Value.Escape == escape)
                    return true;
            }

            return false;
        }

        /// <summary>
        /// 判断是否存在某操作符
        /// </summary>
        /// <param name="identifier"></param>
        /// <returns></returns>
        public static bool ExistOperator(string identifier) 
        {
            if (_tblOperator.ContainsKey(identifier))
                return true;

            return false;
        } 

        /// <summary>
        /// 判断是否存在某函数
        /// </summary>
        /// <param name="identifier"></param>
        /// <returns></returns>
        public static bool ExistFunction(string identifier) 
        {
            if (_tblFunction.ContainsKey(identifier))
                return true;

            return false;
        }

        /// <summary>
        /// 判断是否存在某变量
        /// </summary>
        /// <param name="varName"></param>
        /// <returns></returns>
        public static bool ExistVariable(string varName)
        {
            return _tblGlobalVar.ContainsKey(varName) || _tbUnBuiltInVar.ContainsKey(varName);
        }

        /// <summary>
        /// 判断是否是数值型
        /// </summary>
        /// <param name="varName"></param>
        /// <returns></returns>
        public static bool bNumarical(string varName)
        {
            if (Regex.IsMatch(varName, "^([0-9]{1,})$"))
                return true;

            if (Regex.IsMatch(varName, "^([0-9]{1,}[.][0-9]*)$"))
                return true;

            return false;
        }

        /// <summary>
        /// 取得操作符优先级
        /// </summary>
        /// <param name="identifier"></param>
        /// <returns>-1 代表该操作符不存在，正整数包括0为正常结果</returns>
        public static int GetPriority(string identifier) 
        {
            if (_tblOperator.ContainsKey(identifier))
                 return _tblOperator[identifier].Priority;

            if (_tblFunction.ContainsKey(identifier))
                return _tblFunction[identifier].Priority;

            throw new Exception("找不到指定操作符");
        } 

        /// <summary>
        /// 取得操作符定义的操作数个数
        /// </summary>
        /// <param name="identifier"></param>
        /// <returns></returns>
        public static int GetDimension(string identifier) 
        {
            if (_tblOperator.ContainsKey(identifier))
                return _tblOperator[identifier].Dimension;

            if (_tblFunction.ContainsKey(identifier))
                return _tblFunction[identifier].Dimension;

            if (_tblGlobalVar.ContainsKey(identifier))
                return 1;

            throw new Exception("找不到指定操作符");
        } 

        /// <summary>
        /// 取得最大标示符长度
        /// </summary>
        /// <returns></returns>
        public static int GetMaxIdentifierLen() 
        { 
            return MAX_IDENTIFIER_LEN; 
        } 

        /// <summary>
        /// 取得单词类型
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public static TokenType GetTokenType(string token) 
        {
            if (bValueOperator(token))
                return TokenType.VALUE_OPERATOR;

            if (ExistOperator(token))
                return TokenType.OPERATOR;

            if (ExistVariable(token))
                return TokenType.VARIABLE;

            if (ExistFunction(token))
                return TokenType.FUNCTION;

            if (bNumarical(token))
                return TokenType.NUMARICAL;

            return TokenType.CONST_STRING;
        }

        /// <summary>
        /// 移除用户注册的临时变量
        /// </summary>
        public static void ReleaseUnBuiltInVariable()
        {
            _tbUnBuiltInVar.Clear();
        }
    }
}
